home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dc1 / cexp.c.old < prev    next >
Text File  |  1995-12-24  |  22KB  |  884 lines

  1.  
  2. /*
  3.  *  CEXP.C
  4.  *
  5.  *  Expression Parser.    These routines generate an expression tree.
  6.  *
  7.  *  unary: ! ~ & * ++ -- [exp] (..,..)
  8.  *
  9.  *  binary: % %= & && &= * *= + += , - -= -> . / /= << <<= =
  10.  *        >> >>= ^ ^= | || |=
  11.  *                            precedence
  12.  *  boolean:    < <= == >= > !=
  13.  *                         postf: () [] -> .
  14.  *  special:    exp ? exp : exp          unary: ! ~ ++ -- - * & sizeof
  15.  *                         bin:   * / %
  16.  *  terminator: (exp)                    + -
  17.  *        varid                    << >>
  18.  *        tokid (procedure call?)         < <= > >=
  19.  *        constant                == !=
  20.  *                            &
  21.  *                            ^
  22.  *                            |
  23.  *                            &&
  24.  *                            ||
  25.  *                            ?:
  26.  *                            = += -= *= /= %= |= &= ^= >>= <<=
  27.  *                            ,
  28.  */
  29.  
  30. /*
  31. **      $Filename: cexp.c $
  32. **      $Author: dice $
  33. **      $Revision: 30.325 $
  34. **      $Date: 1995/12/24 05:38:20 $
  35. **      $Log: cexp.c.old,v $
  36. # Revision 30.325  1995/12/24  05:38:20  dice
  37. # .
  38. #
  39.  * Revision 30.156  1995/01/11  05:04:40  dice
  40.  * .
  41.  *
  42.  * Revision 30.5  1994/06/13  18:37:24  dice
  43.  * .
  44.  *
  45.  * Revision 30.0  1994/06/10  18:04:47  dice
  46.  * .
  47.  *
  48.  * Revision 1.8  1994/04/15  20:41:18  jtoebes
  49.  * Handle trailing commas more properly.
  50.  *
  51.  * Revision 1.7  1994/01/03  13:21:01  jtoebes
  52.  * Fixed BUG10002 - Enforcer hit in DC1.
  53.  * Changed the default for a symbol to be a long instead of a function type.
  54.  *
  55.  * Revision 1.6  1993/11/22  00:28:36  jtoebes
  56.  * Final cleanup to eliminate all cerror() messages with strings.
  57.  *
  58.  * Revision 1.5  1993/10/16  14:59:48  jtoebes
  59.  * Allowed optional comma after last element in an array initialization.
  60.  *
  61.  * Revision 1.4  1993/09/11  23:24:17  jtoebes
  62.  * Fixed BUG00047 - DC1 failes to warn about missing , in initialized expression.
  63.  * Changed logic for comma search to be more rigerous.  All old code should
  64.  * continue to compile.
  65.  *
  66.  * Revision 1.3  1993/09/05  23:56:22  jtoebes
  67.  * Fixed BUG06045 - Enforcer hit for invalid structure definitions.
  68.  * Added code to skip over current level of nesting when too many
  69.  * initializers are given for a structure.
  70.  * Created match_nesting subroutine for general usage to do this.
  71.  *
  72. **/
  73.  
  74. #include "defs.h"
  75.  
  76. #define LR    1        /*    left to right, else        */
  77. #define RL    2        /*    right to left            */
  78. #define QBIN    4        /*    binary operator, else unary */
  79. #define BLR    (LR|QBIN)
  80. #define BRL    (RL|QBIN)
  81.  
  82. #define XX    0    /*  don't care (situation never comes up)   */
  83.  
  84. /*static short ExpPrec[64] = EXPPREC;*/
  85.  
  86. Prototype short CompExp(short, Exp **, long);
  87. Prototype short CompBracedAssign(short, Type *, Exp **, short, Symbol *);
  88. Prototype short match_nesting(short);
  89.  
  90. Local void PushOp(Exp **, Exp **, void (*)(Exp **), long, long);
  91. Local void PushAtom(Exp **, Exp **, void (*)(Exp **));
  92. Local void CombineOp(Exp **, Exp **);
  93.  
  94. Exp *HackTmpExp;        /*  free expression cache   */
  95.  
  96. short
  97. CompExp(short t, Exp **pexp, long commaok)
  98. {
  99.     short unary = 1;        /*  operator state  */
  100.     short notdone = 1;
  101.     short parens = 0;
  102.     short quests = 0;        /*  # of question marks for colons */
  103.     Exp   *opStack = NULL;    /*  operator stack  */
  104.     Exp   *atomStack = NULL;    /*  atom stack        */
  105.  
  106.  
  107.     if (t == TokSemi)
  108.     zerror(EFATAL_EXPECTED_EXP);
  109.  
  110.     *pexp = NULL;
  111.  
  112.     for (;;) {
  113.     if (unary) {        /*    construct quantity  */
  114.         switch(t) {
  115.         case TokNot:    /*  !exp    */
  116.         PushOp(&atomStack, &opStack, GenNot, 140, RL);
  117.         break;
  118.         case TokAnd:    /*  &exp    */
  119.         PushOp(&atomStack, &opStack, GenAddr, 140, RL);
  120.         opStack->ex_Token = TokAddr;
  121.         break;
  122.         case TokStar:    /*  *exp    */
  123.         PushOp(&atomStack, &opStack, GenInd, 140, RL);
  124.         break;
  125.         case TokPlPl:    /*  ++exp   */
  126.         PushOp(&atomStack, &opStack, GenPreInc, 140, RL);
  127.         opStack->ex_Token = TokPreInc;
  128.         break;
  129.         case TokMiMi:    /*  --exp   */
  130.         PushOp(&atomStack, &opStack, GenPreDec, 140, RL);
  131.         opStack->ex_Token = TokPreDec;
  132.         break;
  133.         case TokPl:     /*  +exp    */
  134.         break;
  135.         case TokMi:     /*  -exp    */
  136.         PushOp(&atomStack, &opStack, GenNeg, 140, RL);
  137.         break;
  138.         case TokTilde:    /*  ~exp    */
  139.         PushOp(&atomStack, &opStack, GenCompl, 140, RL);
  140.         break;
  141.         case TokSizeof:    /*  sizeof exp    */
  142.         t = GetToken();
  143.         if (t == TokLParen) {    /*  check sizeof(type)    */
  144.             Type *baseType;
  145.             Type *type;
  146.             Symbol *sym;
  147.             long  baseFlags;
  148.             long  regFlags;
  149.  
  150.             t = GetToken();
  151.  
  152.             switch(t) {
  153.             case TokStruct:
  154.             case TokEnum:
  155.             case TokUnion:
  156.             case TokTypeQual:
  157.             case TokRegQual:
  158.             case TokTypeId:
  159.             case TokTypeof:
  160.             t = CompType(t, &baseType, &baseFlags, ®Flags);
  161.             type = baseType;
  162.             t = CompTypeDeclarators(t, &type, &sym, baseFlags);
  163.             if (t != TokRParen)
  164.                 zerror(EFATAL_SYNTAX_ERROR_EXP);
  165.             t = GetToken();
  166.             PushAtom(&atomStack, &opStack, GenSizeof);
  167.             atomStack->ex_Type = type;
  168.             unary = 0;
  169.             continue;
  170.             default:
  171.             PushOp(&atomStack, &opStack, GenSizeof, 140, RL);
  172.             ++parens;
  173.             PushOp(&atomStack, &opStack, GenParen, 0, XX);
  174.             opStack->ex_Token = TokLParen;
  175.             continue;   /*    already have next token after paren */
  176.             }
  177.         }
  178.         PushOp(&atomStack, &opStack, GenSizeof, 140, RL);
  179.         continue;    /*  already have next token */
  180.  
  181.         case TokLParen:    /*  (exp)  or (type) or ()  */
  182.         {
  183.             Type *baseType;
  184.             Type *type;
  185.             Symbol *sym;
  186.             long  baseFlags;
  187.             long  regFlags;
  188.  
  189.             t = GetToken();
  190.  
  191.             switch(t) {     /*  (typecast)    */
  192.             case TokStruct:
  193.             case TokEnum:
  194.             case TokUnion:
  195.             case TokTypeQual:
  196.             case TokRegQual:
  197.             case TokTypeId:
  198.             case TokTypeof:
  199.             t = CompType(t, &baseType, &baseFlags, ®Flags);
  200.             type = baseType;
  201.             t = CompTypeDeclarators(t, &type, &sym, baseFlags);
  202.             if (t != TokRParen)
  203.                 zerror(EFATAL_SYNTAX_ERROR_EXP);
  204.             t = GetToken();
  205.             PushOp(&atomStack, &opStack, GenCast, 140, RL);
  206.             opStack->ex_Type = type;
  207.             opStack->ex_Token = TokCast;
  208.             continue;
  209.             case TokRParen:
  210.             PushAtom(&atomStack, &opStack, GenParen);
  211.             unary = 0;
  212.             t = GetToken();
  213.             continue;
  214.             default:        /*  (exp)   */
  215.             ++parens;
  216.             PushOp(&atomStack, &opStack, GenParen, 0, XX);
  217.             opStack->ex_Token = TokLParen;
  218.             continue;   /*    already have next symbol  */
  219.             }
  220.         }
  221.         /* not reached */
  222.         Assert(0);
  223.                 /*  terminator    */
  224.         case TokEnumConst:
  225.         LexIntConst = (long)LexData;
  226.         LexUnsigned = 0;
  227.         case TokIntConst:
  228.         PushAtom(&atomStack, &opStack, GenIntConst);
  229.         atomStack->ex_Stor.st_IntConst = LexIntConst;
  230.         atomStack->ex_Token = t;
  231.         if (LexUnsigned)
  232.             atomStack->ex_Stor.st_Flags |= SF_UNSIGNED;
  233.         unary = 0;
  234.         break;
  235.         case TokStrConst:
  236.         PushAtom(&atomStack, &opStack, GenStrConst);
  237.         atomStack->ex_StrConst = LexStrConst;
  238.         atomStack->ex_StrLen   = LexStrLen;
  239.         atomStack->ex_Token = t;
  240.         unary = 0;
  241.         break;
  242.         case TokFltConst:
  243.         PushAtom(&atomStack, &opStack, GenFltConst);
  244.         atomStack->ex_Stor.st_FltConst = LexStrConst;
  245.         atomStack->ex_Stor.st_FltLen   = LexStrLen;
  246.         atomStack->ex_Token = t;
  247.         atomStack->ex_Type  = LexData;
  248.         unary = 0;
  249.         break;
  250.         case TokVarId:
  251.         /*
  252.          *  If this is a global or external variable, NOT a procedure,
  253.          *  and not already dummied, then add a dummy semantic entry
  254.          *  and var structure to the highest block in the procedure.
  255.          *
  256.          *  we can't put it in lower blocks due to the possibility
  257.          *  of goto past the lea in case it's lea is stuck into a
  258.          *  register.
  259.          */
  260.         {
  261.             Var *var = (Var *)LexData;
  262.  
  263.             PushAtom(&atomStack, &opStack, GenVarRef);
  264.             atomStack->ex_Token = TokVarRef;
  265.             atomStack->ex_Symbol = LexSym;
  266.             atomStack->ex_Var  = var;
  267.             atomStack->ex_Var->Refs += BlockCost + 1;
  268.             unary = 0;
  269.         }
  270.         break;
  271.         case TokId:     /*  possible subroutine?    */
  272.         t = GetToken();
  273.         {
  274.             Var *var = AllocStructure(Var);
  275.  
  276.             if (t != TokLParen)
  277.             {
  278.             zerror(EERROR_UNDEFINED_SYMBOL, SymToString(LexSym));
  279.             /* default is a long */
  280.             var->Type = &LongType;
  281.             }
  282.             else
  283.             {
  284.             /* They used it as a procedure */
  285.             /*
  286.              *  create a variable as a reference to the procedure
  287.              *  specified returning an int.
  288.              */
  289.             var->Type = &DefaultProcType;
  290.             }
  291.  
  292.  
  293.             var->Sym  = LexSym;
  294.             var->Flags = TF_EXTERN;
  295.             var->LexIdx= LFBase->lf_Index;  /* XXX */
  296.  
  297.             BlockAddTop(var);
  298.             SemanticAddTop(LexSym, TokVarId, var); /* XXX */
  299.  
  300.             PushAtom(&atomStack, &opStack, GenVarRef);
  301.             atomStack->ex_Token = TokVarRef;
  302.             atomStack->ex_Symbol= LexSym;
  303.             atomStack->ex_Var    = var;
  304.             ++atomStack->ex_Var->Refs;
  305.         }
  306.         unary = 0;
  307.         continue;    /*  have token */
  308.         default:
  309.         notdone = 0;
  310.         break;
  311.         }
  312.     } else {
  313.         unary = 1;
  314.  
  315.         switch(t) {
  316.         case TokNotEq:    /*  boolean    */
  317.         case TokEqEq:
  318.         PushOp(&atomStack, &opStack, GenBoolCompareSame, 90, BLR);
  319.         opStack->ex_Token = t;
  320.         break;
  321.         case TokLt:
  322.         case TokLtEq:
  323.         case TokGtEq:
  324.         case TokGt:
  325.         PushOp(&atomStack, &opStack, GenBoolCompare, 100, BLR);
  326.         opStack->ex_Token = t;
  327.         break;
  328.         case TokPercentEq:
  329.         PushOp(&atomStack, &opStack, GenPercentEq, 20, BRL);
  330.         break;
  331.         case TokAndEq:
  332.         PushOp(&atomStack, &opStack, GenAndEq, 20, BRL);
  333.         break;
  334.         case TokStarEq:
  335.         PushOp(&atomStack, &opStack, GenStarEq, 20, BRL);
  336.         break;
  337.         case TokMiEq:
  338.         PushOp(&atomStack, &opStack, GenMiEq, 20, BRL);
  339.         break;
  340.         case TokDivEq:
  341.         PushOp(&atomStack, &opStack, GenDivEq, 20, BRL);
  342.         break;
  343.         case TokLtLtEq:
  344.         PushOp(&atomStack, &opStack, GenLtLtEq, 20, BRL);
  345.         break;
  346.         case TokGtGtEq:
  347.         PushOp(&atomStack, &opStack, GenGtGtEq, 20, BRL);
  348.         break;
  349.         case TokPlEq:
  350.         PushOp(&atomStack, &opStack, GenPlEq, 20, BRL);
  351.         break;
  352.         case TokEq:
  353.         PushOp(&atomStack, &opStack, GenEq, 20, BRL);
  354.         break;
  355.         case TokOrEq:
  356.         PushOp(&atomStack, &opStack, GenOrEq, 20, BRL);
  357.         break;
  358.         case TokCaratEq:
  359.         PushOp(&atomStack, &opStack, GenCaratEq, 20, BRL);
  360.         break;
  361.  
  362.         case TokAndAnd:
  363.         PushOp(&atomStack, &opStack, GenAndAnd, 50, BLR);
  364.         break;
  365.         case TokOrOr:
  366.         PushOp(&atomStack, &opStack, GenOrOr, 40, BLR);
  367.         break;
  368.  
  369.         case TokDiv:
  370.         PushOp(&atomStack, &opStack, GenDiv, 130, BLR);
  371.         break;
  372.         case TokPercent:
  373.         PushOp(&atomStack, &opStack, GenPercent, 130, BLR);
  374.         break;
  375.         case TokStar:
  376.         PushOp(&atomStack, &opStack, GenStar, 130, BLR);
  377.         break;
  378.         case TokMi:
  379.         PushOp(&atomStack, &opStack, GenMi, 120, BLR);
  380.         opStack->ex_Token = TokMi;
  381.         break;
  382.         case TokPl:
  383.         PushOp(&atomStack, &opStack, GenPl, 120, BLR);
  384.         opStack->ex_Token = TokPl;
  385.         break;
  386.  
  387.         case TokAnd:
  388.         PushOp(&atomStack, &opStack, GenAnd, 80, BLR);
  389.         break;
  390.         case TokOr:
  391.         PushOp(&atomStack, &opStack, GenOr, 60, BLR);
  392.         break;
  393.         case TokCarat:
  394.         PushOp(&atomStack, &opStack, GenXor, 70, BLR);
  395.         break;
  396.         case TokLtLt:
  397.         PushOp(&atomStack, &opStack, GenLShf, 110, BLR);
  398.         break;
  399.         case TokGtGt:
  400.         PushOp(&atomStack, &opStack, GenRShf, 110, BLR);
  401.         break;
  402.  
  403.         case TokQuestion:
  404.         PushOp(&atomStack, &opStack, GenQuestion, 30, BRL);
  405.         opStack->ex_Token = TokQuestion;
  406.         opStack->ex_Precedence = 0;
  407.         ++quests;
  408.         break;
  409.  
  410.         case TokColon:
  411.         if (quests == 0) {
  412.             notdone = 0;
  413.             break;
  414.         }
  415.         --quests;
  416.         /*
  417.          *  Combine opstack until the op is GenQuestion.  After
  418.          *  all is said and done the tree looks like:        :
  419.          *                           / \
  420.          *            a ? b : c          ?   c
  421.          *                         a b
  422.          */
  423.         while (opStack && opStack->ex_Token != TokQuestion)
  424.             CombineOp(&atomStack, &opStack);
  425.         if (opStack == NULL)
  426.             zerror(EFATAL, EFATAL_SYNTAX_ERROR_EXP);
  427.         CombineOp(&atomStack, &opStack);    /*    atom for a ? b    */
  428.         PushOp(&atomStack, &opStack, GenColon, 30, BRL);
  429.         break;
  430.  
  431.         /*
  432.          *    postfix operators, we stay in binary mode
  433.          */
  434.  
  435.         case TokLParen:
  436.         /*
  437.          *  Subroutine call.
  438.          */
  439.  
  440.         unary = 0;
  441.         t = GetToken();
  442.         {
  443.             Exp *exp = NULL;
  444.             Exp **pe = &exp;
  445.  
  446.             while (t && t != TokRParen) {
  447.             Exp *e;
  448.  
  449.             t = CompExp(t, pe, 0);
  450.             e = *pe;
  451.             pe = &e->ex_Next;
  452.             if (t != TokComma && t != TokRParen) {
  453.                 zerror(EFATAL_EXPECTED_COMMACLOSE);
  454.                 break;
  455.             }
  456.             if (t == TokComma)
  457.                 t = GetToken();
  458.             }
  459.             PushOp(&atomStack, &opStack, GenCall, 150, LR);
  460.             opStack->ex_ExpR = exp;
  461.             opStack->ex_Token= TokCall;
  462.         }
  463.         break;
  464.         case TokRParen:
  465.         unary = 0;
  466.         if (parens == 0) {
  467.             notdone = 0;
  468.             break;
  469.         }
  470.         --parens;
  471.         /*
  472.          *  Combine until we find the GenParen
  473.          */
  474.         while (opStack && opStack->ex_Token != TokLParen)
  475.             CombineOp(&atomStack, &opStack);
  476.         if (opStack == NULL)
  477.             zerror(EFATAL_SYNTAX_ERROR_EXP);
  478.         CombineOp(&atomStack, &opStack);    /*  now have atom for (exp) */
  479.         break;
  480.         case TokComma:
  481.         unary = 1;
  482.         if (parens == 0 && commaok == 0) {
  483.             notdone = 0;
  484.             break;
  485.         }
  486.         PushOp(&atomStack, &opStack, GenComma, 10, BLR);
  487.         break;
  488.         case TokPlPl:   /*    exp++    */
  489.         unary = 0;
  490.         PushOp(&atomStack, &opStack, GenPosInc, 150, LR);
  491.         opStack->ex_Token = TokPosInc;
  492.         break;
  493.         case TokMiMi:
  494.         unary = 0;
  495.         PushOp(&atomStack, &opStack, GenPosDec, 150, LR);
  496.         opStack->ex_Token = TokPosDec;
  497.         break;
  498.         case TokStrInd:
  499.         case TokStrElm:
  500.         unary = 0;
  501.         {
  502.             void (*func)(Exp **) = ((t == TokStrInd) ? GenStructInd : GenStructElm);
  503.  
  504.             PushOp(&atomStack, &opStack, GenStructInd, 150, LR);
  505.             t = GetToken();
  506.             if (t != TokId && /* t != TokLabelId && */ t != TokVarId && t != TokTypeId && t != TokEnumConst)
  507.             zerror(EFATAL_EXPECTED_STRUCT_TAG);
  508.             opStack->ex_Func = func;
  509.             opStack->ex_Symbol = LexSym;
  510.         }
  511.         break;
  512.         case TokLBracket:
  513.         unary = 0;
  514.         {
  515.             Exp *exp;
  516.  
  517.             t = CompExp(GetToken(), &exp, 1);
  518.             if (t != TokRBracket)
  519.             zerror(EERROR_EXPECTED_CLOSE_BRACKET);
  520.             PushOp(&atomStack, &opStack, GenArray, 150, LR);
  521.             opStack->ex_ExpR = exp;
  522.         }
  523.         break;
  524.         default:
  525.         notdone = 0;
  526.         break;
  527.         }
  528.     }
  529.     if (notdone) {
  530.         t = GetToken();
  531.         continue;
  532.     }
  533.     break;
  534.     }
  535.     while (opStack)
  536.     CombineOp(&atomStack, &opStack);
  537.     if (atomStack == NULL)
  538.     zerror(EFATAL_SYNTAX_ERROR_EXP);
  539.     if (parens)
  540.     zerror(EFATAL_EXPECTED_CLOSE_PARENS, parens);
  541.     if (atomStack->ex_Next)
  542.     zerror(EFATAL_SYNTAX_ERROR_EXP);
  543.     atomStack->ex_Next = NULL;
  544.     *pexp = atomStack;
  545.  
  546.     return(t);
  547. }
  548.  
  549. /*
  550.  *  precedence of 0 is for parenthesized expressions and never combines.
  551.  */
  552.  
  553. Local  void
  554. PushOp(patomStack, popStack, genFunc, precedence, order)
  555. Exp **patomStack;
  556. Exp **popStack;
  557. void (*genFunc)(Exp **);
  558. long precedence;
  559. long order;
  560.  
  561. {
  562.     Exp *exp;
  563.  
  564.     /*
  565.      *    If precedence then pop stack until get entry with lower precedence,
  566.      *    equal precedence breaks out only for left-to-right operations.
  567.      *    Parsing : in a ?: expression ignores precedence until ? is found
  568.      *    again.
  569.      */
  570.  
  571.     if (precedence) {
  572.     for (exp = *popStack; exp; exp = *popStack) {
  573.         if (precedence > exp->ex_Precedence)
  574.         break;
  575.         if (precedence == exp->ex_Precedence && (order & RL))
  576.         break;
  577.         CombineOp(patomStack, popStack);
  578.     }
  579.     }
  580.     exp = AllocTmpStructure(Exp);
  581.     exp->ex_Precedence = precedence;
  582.     exp->ex_Order = order;
  583.     exp->ex_Func = genFunc;
  584.     exp->ex_Next = *popStack;
  585.     exp->ex_LexIdx = LFBase->lf_Index;
  586.     *popStack = exp;
  587. }
  588.  
  589. Local  void
  590. PushAtom(patomStack, popStack, genFunc)
  591. Exp **patomStack;
  592. Exp **popStack;
  593. void (*genFunc)(Exp **);
  594. {
  595.     Exp *exp;
  596.  
  597.     if (HackTmpExp) {
  598.     exp = HackTmpExp;
  599.     setmem(exp, sizeof(Exp), 0);
  600.     HackTmpExp = NULL;
  601.     } else {
  602.     exp = AllocTmpStructure(Exp);
  603.     }
  604.  
  605.     exp->ex_Func = genFunc;
  606.     exp->ex_Next = *patomStack;
  607.     exp->ex_LexIdx = LFBase->lf_Index;
  608.     exp->ex_Flags= 0;
  609.     *patomStack = exp;
  610. }
  611.  
  612. Local  void
  613. CombineOp(patomStack, popStack)
  614. Exp **patomStack;
  615. Exp **popStack;
  616. {
  617.     Exp *exp = *popStack;    /*  get op  */
  618.     Exp *e1;
  619.     Exp *e2;
  620.  
  621.     if (exp == NULL)
  622.     zerror(EFATAL_SYNTAX_ERROR_EXP);
  623.     if ((e1 = *patomStack) == NULL)
  624.     zerror(EFATAL_SYNTAX_ERROR_EXP);
  625.  
  626.     if (exp->ex_Order & QBIN) {
  627.     e2 = e1->ex_Next;
  628.     if (e2 == NULL)
  629.         zerror(EFATAL_SYNTAX_ERROR_EXP);
  630.     *patomStack = e2->ex_Next;
  631.     exp->ex_ExpL = e2;
  632.     exp->ex_ExpR = e1;
  633.     exp->ex_Flags = 0;
  634.     /*exp->ex_Flags = (e1->ex_Flags | e2->ex_Flags) & EF_CALL;*/
  635.  
  636.     } else {
  637.     *patomStack = e1->ex_Next;
  638.     exp->ex_ExpL = e1;
  639.     exp->ex_Flags = 0;
  640.  
  641.     if (exp->ex_Token == TokCall && e1->ex_Token == TokVarRef) {
  642.         char prgno[16];
  643.         PragNode *pragma_call;
  644.  
  645.         if ((pragma_call = TestPragmaCall(e1->ex_Var, prgno)) != NULL) {
  646.         /*
  647.          *  Append base variable reference - A6 to end of
  648.          *  argument list.
  649.          */
  650.         Exp *ex = zalloc(sizeof(Exp));
  651.         Exp **pexp;
  652.         Symbol *sym = MakeSymbol(pragma_call->pn_Sym->Name, pragma_call->pn_Sym->Len, TokId, NULL);
  653.  
  654.         if (sym->LexId != TokVarId)
  655.             yerror(exp->ex_LexIdx, EFATAL_PRAGMA_BASE_UNDEF, sym->Len, sym->Name);
  656.  
  657.         for (pexp = &exp->ex_ExpR; (e1 = *pexp) != NULL; pexp = &e1->ex_Next)
  658.             ;
  659.         ex->ex_Func = GenVarRef;
  660.         ex->ex_Token = TokVarRef;
  661.         ex->ex_Symbol = sym;
  662.         ex->ex_Var = sym->Data;
  663.         ex->ex_Flags |= EF_SPECIAL;
  664.         ++ex->ex_Var->Refs;
  665.         *pexp = ex;
  666.         }
  667.     }
  668.     }
  669.     *popStack = exp->ex_Next;
  670.     exp->ex_Next = *patomStack;
  671.     *patomStack = exp;
  672. }
  673.  
  674. /*
  675.  *  Parse a braced expression.    An open brace refers to an explcit
  676.  *  downlevel while an expression may cause zero or more implicit
  677.  *  downlevel's.
  678.  *
  679.  *  exp->ex_Token is set to TokExpAssBlock for downlevel exp's
  680.  *  exp->ex_ExpL is the base of a list of expressions linked via ex_Next
  681.  */
  682.  
  683. short
  684. CompBracedAssign(short t, Type *type, Exp **pexp, short lbraced, Symbol *sym)
  685. {
  686.     Exp *exp;
  687.     long **caBase;
  688.     long index = 0;
  689.     int wantcomma;
  690.  
  691.     /*
  692.      *    create downlevel
  693.      */
  694.  
  695.     *pexp = exp = AllocTmpStructure(Exp);
  696.     pexp = &exp->ex_ExpL;
  697.     exp->ex_Type = type;
  698.     exp->ex_Token = TokExpAssBlock;
  699.     exp->ex_LexIdx = LFBase->lf_Index;
  700.     exp->ex_Func  = GenBracedAssign;
  701.     caBase = &exp->ex_ConstAry;
  702.  
  703.     for (;;) {
  704.     Type *subType;
  705.  
  706.         wantcomma = 0;
  707.     if (type->Id == TID_STRUCT) {
  708.         if (index >= type->Args)
  709.         break;
  710.         subType = type->Vars[index]->Type;
  711.         if (index) wantcomma = 1;
  712.     } else if (type->Id == TID_UNION) {
  713.         if (index)
  714.         break;
  715.         subType = type->Vars[0]->Type;
  716.     } else if (type->Id == TID_ARY) {
  717.         subType = type->SubType;
  718.         if (type->Size && index >= type->Size / subType->Size)
  719.         break;
  720.         if (index) wantcomma = 1;
  721.     } else {
  722.         subType = type;
  723.     }
  724.     if (subType->Id == TID_UNION || subType->Id == TID_STRUCT || subType->Id == TID_ARY) {
  725.         /*
  726.          *    level-down
  727.          */
  728.  
  729.             if (wantcomma)
  730.             {
  731.                 if (t == TokComma)
  732.                     t = GetToken();
  733.                 else
  734.                 {
  735.                     zerror(EWARN_MISSING_COMMA);
  736.                 }
  737.             }
  738.  
  739.         if (t == TokLBrace) {
  740.         t = CompBracedAssign(GetToken(), subType, pexp, 1, NULL);
  741.         if (t != TokRBrace)
  742.         {
  743.             zerror(EERROR_TOO_MANY_INITIALIZERS);
  744.             t = match_nesting(t);
  745.         }
  746.         t = GetToken();
  747.         } else {
  748.         t = CompBracedAssign(t, subType, pexp, 0, NULL);
  749.         }
  750.         ++index;
  751.         pexp = &(*pexp)->ex_Next;
  752.         if (t == TokRBrace || t == TokSemi)
  753.         break;
  754.     } else {
  755.         /*
  756.          *    terminal case for subType
  757.          *
  758.          *    A right-brace here may terminate the sequence, possible
  759.          *    unto multiple levels.
  760.          */
  761.  
  762.         if (t == TokRBrace || t == TokSemi)
  763.         break;
  764.  
  765.             if (wantcomma)
  766.             {
  767.                 if (t == TokComma)
  768.                     t = GetToken();
  769.                 else
  770.                 {
  771.                     zerror(EWARN_MISSING_COMMA);
  772.                 }
  773.                 if (t == TokRBrace)
  774.                 {
  775.                    break;
  776.                 }
  777.             }
  778.  
  779.         if (t == TokStrConst && type->Id == TID_ARY && subType->Size == 1) {
  780.         Exp *sexp;
  781.  
  782.         t = CompExp(t, pexp, 0);
  783.         sexp = *pexp;
  784.         Assert(sexp->ex_Token == TokStrConst);
  785.         index += sexp->ex_StrLen;
  786.  
  787.         /*
  788.          *  quietly delete the terminating \0 if string
  789.          *  overruns array.
  790.          */
  791.  
  792.         if (type->Size) {
  793.             if (index > type->Size) {
  794.             if (index - 1 == type->Size) {
  795.                 --index;
  796.                 --sexp->ex_StrLen;
  797.             } else {
  798.                 sexp->ex_StrLen -= (index - type->Size);
  799.                 index = type->Size;
  800.                 zerror(EERROR_ARRAY_CANNOT_HOLD_STRING);
  801.             }
  802.             } else if (index < type->Size && lbraced == 0) {
  803.             /*
  804.              *  If no { } was used to explicitly specify
  805.               *  initializers for this array, the string will
  806.              *  force the array to be terminated & zero filled
  807.              */
  808.  
  809.             long newLen = type->Size - index + sexp->ex_StrLen;
  810.             char *new = talloc(newLen);
  811.             movmem(sexp->ex_StrConst, new, sexp->ex_StrLen);
  812.  
  813.             sexp->ex_StrConst = new;
  814.             sexp->ex_StrLen = newLen;
  815.             index = type->Size;
  816.             }
  817.         }
  818.         pexp = &(*pexp)->ex_Next;
  819.         break;
  820.         } else {
  821.         /*
  822.          *  This is the nominal core, and where all the memory is
  823.          *  eaten up for statically initialized arrays.  Simple
  824.          *  integer constants are optimized (so we do not allocate
  825.          *  an entire Exp structure for each constant).
  826.          */
  827.  
  828.         t = CompExp(t, pexp, 0);
  829.         if (pexp == &exp->ex_ExpL && (*pexp)->ex_Token == TokIntConst) {
  830.             long *captr = talloc(sizeof(long) * 2);
  831.             Exp  *caexp = *pexp;
  832.  
  833.             *caBase = captr;
  834.             captr[1] = caexp->ex_Stor.st_IntConst;
  835.  
  836.             caBase = (long **)&captr[0];
  837.             HackTmpExp = caexp;
  838.             *pexp = NULL;
  839.         } else {
  840.             pexp = &(*pexp)->ex_Next;
  841.         }
  842.         ++index;
  843.         }
  844.  
  845.     }
  846.     if (subType == type) break;
  847.     }
  848.     *pexp = NULL;
  849.     *caBase = NULL;
  850.     HackTmpExp = NULL;        /*    don't leave stale cache */
  851.  
  852.     if (type->Id == TID_ARY && lbraced)
  853.     {
  854.        if (t == TokComma)
  855.           t = GetToken();
  856.     }
  857.     if (type->Size == 0)
  858.     {
  859.     if (type->Id == TID_ARY)
  860.         type->Size = index * type->SubType->Size;
  861.     else if (type->Id == TID_UNION || type->Id == TID_STRUCT)
  862.     {
  863.         Undefined_Tag(type, sym, exp->ex_LexIdx);
  864.         t = match_nesting(t);
  865.     }
  866.     }
  867.     return(t);
  868. }
  869.  
  870. short match_nesting(short t)
  871. {
  872.     int nesting = 1;
  873.     /* We now want to eat up all of the outstanding tokens to avoid a */
  874.     /* cascade of errors.                                             */
  875.     while(nesting)
  876.     {
  877.     if (t == TokRBrace) nesting--;
  878.     else if (t == TokLBrace) nesting++;
  879.     else if (t == 0) break;
  880.     if (nesting) t = GetToken();
  881.     }
  882.     return(t);
  883. }
  884.